package org.dei.perla.sys.llqruntime;

import java.util.ArrayList;
import org.dei.perla.parser.expressions.*;

/**
 * Permette di analizzare le espressioni alla ricerca di campi oggetto logico.
 * @author Camplani, Fortunato, Marelli, Rota et al.
 *
 */
public class ExpressionAnalyzer {
	
	private ArrayList<NodeLogicalObjectAttribute> tNodeArrayList = new ArrayList<NodeLogicalObjectAttribute>();
	
	/**
	 * Costruttore della classe ExpressionAnalyzer
	 */
	public ExpressionAnalyzer() {	
		
	}
	

	/**
	 * Metodo helper privato che si occupa di analizzare se un singolo nodo è un campo oggetto logico
	 * @param parNode Il nodo da analizzare
	 */
	private void getFields(Node parNode) {
					
		if (parNode instanceof NodeOperation) {
			
			this.getFields(((NodeOperation) parNode).getFirstNode(), ((NodeOperation) parNode).getSecondNode());
			
		}
		else if (parNode instanceof NodeAggregation) {
			
			this.getFields(((NodeAggregation) parNode).getExpressionToAggregate());
			
		} 
		else if (parNode instanceof NodeBetween) {
			
			this.getFields(((NodeBetween) parNode).getFirstNode(), ((NodeBetween) parNode).getSecondNode(), ((NodeBetween) parNode).getThirdNode());
			
		}
		else if (parNode instanceof NodeFunction) {
			
			this.getFields(((NodeFunction) parNode).getFunctionPar());
			
		}
		else if (parNode instanceof NodeLogicalObjectAttribute && !this.tNodeArrayList.contains(parNode)) {
		
			this.tNodeArrayList.add((NodeLogicalObjectAttribute)parNode);
			
		}
		
	}
	
	/**
	 * Metodo helper che si occupa di analizzare un nodo con due "figli" alla ricerca di campi
	 * @param parFirstNode Il primo nodo
	 * @param parSecondNode Il secondo nodo
	 */
	private void getFields(Node parFirstNode, Node parSecondNode) {
		
		this.getFields(parFirstNode);
		if (parSecondNode!=null) {this.getFields(parSecondNode);}
		
	}
	
	/**
	 * Metodo helper che analizza i Nodi con tre figli (e.g. NodeBetween)
	 * @param parFirstNode Il primo nodo
	 * @param parSecondNode Il secondo nodo
	 * @param parThirdNode Il terzo nodo
	 */
	private void getFields(Node parFirstNode, Node parSecondNode, Node parThirdNode) {
		
		this.getFields(parFirstNode);
		this.getFields(parSecondNode);
		this.getFields(parThirdNode);
		
	}
	
	/**
	 * Ottiene l'arrayList di tutti i "campi oggetto logico" dei nodi contenuti in un arraylist
	 * @param parArrayListNode l'arrayList contente i nodi
	 */
	public ArrayList<NodeLogicalObjectAttribute> getFields(ArrayList<Node> parArrayListNode) {
		
		for (Node tNode : parArrayListNode) {
			
			this.getFields(tNode);
			
		}
		return this.tNodeArrayList;
		
	}
	
	/**
	 * Metodo per ottenere l'ArrayList di tutti i "campi oggetto logico" partendo da un nodo radice
	 * @param parNode Il nodo radice dell'espressione
	 * @return ArrayList contenente i "campi oggetto logico" trovati
	 */
	public ArrayList<NodeLogicalObjectAttribute> getNodeArrayList(Node parNode) {
		
		getFields(parNode);
		return this.tNodeArrayList;
		
	}
}
